#pragma once

#include <vector>
#include "interface/common.h"
#include "enum.h"

// 子道: 只可在x轴方向移动的点，即二领域点
// 母道: 可以在x和y轴方向移动的点，即四领域点

// 将仓位分成四个区域，具体定义如下：
// 默认仓位点设置为kUnknown,
// 1. 如果仓位在最左侧，即仓位的左侧没有母道，则将该仓位label设置成kLeft,
// 2. 如果仓位在中间，即仓位的左侧和右侧都有母道，则将该仓位label设置成kMiddle,
// 3. 如果仓位在最右侧，即仓位的右侧没有母道，则将该仓位label设置成kRight,
// 4. 如果仓位点位于母道上，则将该仓位点设置为kFree。

// 将仓位分成N+1个簇(N是母道的行数)，具体定义如下：
// 1. 如果仓位在kLeft区域， 则将该仓位的簇设置成0
// 2. 如果仓位在kMiddle区域， 则将该仓位的簇设置成

// 仓位所处位置的枚举
BETTER_ENUM(Zone, int,
            kUnknown = -1,  //
            kLeft    = 0,   //
            kMiddle  = 1,   //
            kRight   = 2,   //
            kFree    = 3    //
);

// ------------------------------ x
// | 1111111111111111111111111111
// | 1111111111111111111111111111
// | 2222222222222222222222222222
// | 1111111111111111111111111111
// | 1111111111111111111111111111
// | 2222222222222222222222222222
// | 1111111111111111111111111111
// | 2222222222222222222222222222
// | 1111111111111111111111111111
// y
class GridMap {
public:
    GridMap(const std::vector<std::vector<int>>& grid);

    std::vector<int> GreedyPlan(const Point& start, const std::vector<Point>& goals);
    int              Distance(const Point& p1, const Point& p2);

    std::vector<std::vector<int>> GetGrid() { return grid_; };

private:
    // 获取子道的index
    int GetChildIndx(const Point& p) { return p.x; };

    // 是否在母道上
    bool InCross(const Point& p) { return grid_[p.y][p.x] == GridType::kCross; };

    // 2.占据值(1: 普通仓位; 2:交叉口; 8:障碍物)
    std::vector<std::vector<int>> grid_;

    // first: 代表当前点所处的位置，enum Zone类型
    // second: 所属的聚类簇，其定义如下:
    // -2:母道上的点簇
    // -1:最左边区域的簇
    // (0->N-1):中间区域的簇
    // N: 最右边区域的簇
    std::vector<std::vector<std::pair<Zone, int>>> labels_;

    // 地图的高度和宽度
    int height_;
    int width_;

    // 母道所在的行数
    std::vector<int> cross_rows_;
};